<template>
  <el-table
    v-bind="$attrs"
    :data="tableData"
    v-loading="isLoading"
    :element-loading-text="elementLoadingText"
    :element-loading-spinner="elementLoadingSpinner"
    :element-loading-svg="elementLoadingSvg"
    :element-loading-svg-view-box="elementLoadingSvgViewBox"
    :element-loading-background="elementLoadingBackground"
    @row-click="rowClick"
  >
    <template v-for="(item, index) in columnOption" :key="index">
      <el-table-column
        :prop="item.prop"
        :label="item.label"
        :align="item.align"
        :width="item.width"
      >
        <template #default="scope">
          <template v-if="scope.row.rowEdit">
            <el-input size="small" v-model="scope.row[item.prop]"></el-input>
          </template>
          <template v-else>
            <template v-if="scope.$index + scope.column.id === currentEdit">
              <div style="display: flex">
                <el-input
                  size="small"
                  v-model="scope.row[item.prop!]"
                ></el-input>
                <div @click.stop="clickEditCell">
                  <!-- 如果写了插槽内容就用插槽 -->
                  <slot
                    name="editCell"
                    :scope="scope"
                    v-if="$slots.editCell"
                  ></slot>
                  <div class="icons" v-else>
                    <el-icon-check
                      class="check"
                      @click="check(scope)"
                    ></el-icon-check>
                    <el-icon-close
                      class="close"
                      @click="close(scope)"
                    ></el-icon-close>
                  </div>
                </div>
              </div>
            </template>
            <template v-else>
              <slot v-if="item.slot" :name="item.slot" :scope="scope"></slot>
              <span v-else>{{ scope.row[item.prop] }}</span>
              <component
                :is="`el-icon-${toLine(editIcon)}`"
                @click.stop="clickEdit(scope)"
                class="edit"
                v-if="item.editable"
              ></component>
            </template>
          </template>
        </template>
      </el-table-column>
    </template>
    <el-table-column
      :label="actionOption.label"
      :align="actionOption.align"
      :width="actionOption.width"
    >
      <template #default="scope">
        <slot name="editRow" v-if="scope.row.rowEdit"></slot>
        <slot name="action" :scope="scope" v-else></slot>
      </template>
    </el-table-column>
  </el-table>

  <div
    class="pagination"
    :style="{ justifyContent: paginationAlign }"
    v-if="pagination"
  >
    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :page-sizes="pageSizes"
      layout="total, sizes, prev, pager, next, jumper"
      :total="400"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, onMounted, watch } from "vue";
import { TableOptions } from "./types.ts";
import { toLine } from "../../../utils";
import cloneDeep from "lodash/cloneDeep";
let props = withDefaults(defineProps<TableOptions>(), {
  // 可编缉单元格显示的图标
  editIcon: "Edit",
  // 是否可以编辑行
  isEditRow: false,
  // 点击哪个按钮，可以编缉行
  editRowIndex: "",
  pagination: false,
  // 当前是第几页的数据
  currentPage: 1,
  pageSizes: [10, 20, 30, 40],
  pageSize: 10,
  paginationAlign: "left",
});

let currentPage = ref<number>(cloneDeep(props.currentPage));
let pageSize = ref<number>(cloneDeep(props.pageSize));
let paginationAlign = computed(() => {
  if (props.paginationAlign === "left") return "flex-start";
  else if (props.paginationAlign === "center") return "center";
  else return "flex-end";
});
watch(
  () => props.currentPage,
  (val) => {
    currentPage.value = val;
  }
);
watch(
  () => props.pageSize,
  (val) => {
    pageSize.value = val;
  }
);

let currentEdit = ref<string>("");

// 按行编缉，是一行全编缉完才保存，不像单元格编缉可以 v-model="scope.row[item.prop!]"
// 拷贝一份表格的数据
let tableData = ref<any[]>(cloneDeep(props.data));
// 拷贝一份按钮的标识
let cloneEditRowIndex = ref<string>(props.editRowIndex);

watch(
  () => props.data,
  (val) => {
    tableData.value = cloneDeep(val);
    tableData.value.map((item) => {
      // 代表当前是否是可编缉的状态
      item.rowEdit = false;
    });
  },
  { deep: true }
);

// 监听父组件传递过来的标识
watch(
  () => props.editRowIndex,
  (val) => {
    if (val) cloneEditRowIndex.value = val;
  }
);

onMounted(() => {
  tableData.value.map((item) => {
    // 代表当前是否是可编缉的状态
    item.rowEdit = false;
  });
});

let clickEdit = (scope: any) => {
  // 唯一的标识
  currentEdit.value = scope.$index + scope.column.id;
  console.log(scope);
};

// 没有在通用组件里处理的，都是分发事件
let emits = defineEmits([
  "confirm",
  "cancel",
  "update:editRowIndex",
  "sizeChange",
  "currentChange",
]);

let check = (scope: any) => {
  emits("confirm", scope);
};

let clickEditCell = () => {
  currentEdit.value = "";
};

let close = (scope: any) => {
  emits("cancel", scope);
};

let rowClick = (row: any, column: any, event: Event) => {
  if (column.label === actionOption.value.label) {
    if (props.isEditRow && cloneEditRowIndex.value === props.editRowIndex) {
      row.rowEdit = !row.rowEdit;
      tableData.value.map((item) => {
        if (item !== row) {
          item.rowEdit = false;
        }
      });
      if (!row.rowEdit) {
        emits("update:editRowIndex", "");
      }
    }
  }
};

let handleSizeChange = (val: number) => {
  emits("sizeChange", val);
};

let handleCurrentChange = (val: number) => {
  emits("currentChange", val);
};

// 过滤操作选项之后的配置
let columnOption = computed(() => props.options.filter((item) => !item.action));
let actionOption = computed(
  () => props.options.filter((item) => item.action)[0]
);
let isLoading = computed(() => !props.data || !props.data.length);
</script>

<style lang="scss" scoped>
.edit {
  width: 1em;
  height: 1em;
  position: relative;
  top: 2px;
  margin-left: 4px;
  cursor: pointer;
}
.icons {
  display: flex;
  position: relative;
  top: 6px;
  svg {
    width: 1em;
    height: 1em;
    margin-left: 8px;
    cursor: pointer;
  }
  .check {
    color: red;
  }
  .close {
    color: green;
  }
}

.pagination {
  display: flex;
  align-items: center;
  margin-top: 16px;
}
</style>
